<template>
  <div class="cascader">
    <div class="select" ref="selProvinceRef" data-tip="省份">
      <div class="title">
        <span>请选择</span>
        <el-icon><ArrowDown /></el-icon>
      </div>
      <ul class="options"></ul>
    </div>

    <div class="select" ref="selCityRef" data-tip="市区">
      <div class="title">
        <span>请选择</span>
        <el-icon><ArrowDown /></el-icon>
      </div>
      <ul class="options"></ul>
    </div>

    <div class="select" ref="selAreaRef" data-tip="区县">
      <div class="title">
        <span>请选择</span>
        <el-icon><ArrowDown /></el-icon>
      </div>
      <ul class="options"></ul>
    </div>
  </div>
</template>

<script setup>
// 模块引入
import { computed, useTemplateRef, onMounted } from 'vue'
import { ArrowDown } from '@element-plus/icons-vue'
defineOptions({
  // 组件名称
  name: 'Cascade',
  // 继承透传，是否继承没在子组件声明的父组件的属性
  inheritAttrs: true
})

const props = defineProps({
  datas: {
    type: Array,
    default: () => []
  }
})

const selProvinceRef = useTemplateRef('selProvinceRef')
const selCityRef = useTemplateRef('selCityRef')
const selAreaRef = useTemplateRef('selAreaRef')
const datas = computed(() => props.datas)

function fillSelect(select, list) {
  const ul = select.querySelector('.options')
  ul.innerHTML.length && (ul.innerHTML = '')
  if (!list.length) {
    select.classList.add('disabled')
    setTitleText(select, '请选择')
    return
  }

  select.classList.remove('disabled')
  const tip = select.dataset.tip
  setTitleText(select, `请选择${tip}`)
  select.datas = list

  const fragment = document.createDocumentFragment()
  for (const item of list) {
    const li = document.createElement('li')
    li.textContent = item.label
    fragment.appendChild(li)
  }
  ul.appendChild(fragment)

  ul.innerHTML = list.map((obj) => `<li>${obj.label}</li>`).join('')
}

function setTitleText(select, textContent) {
  const span = select.querySelector('.title span')
  span.textContent = textContent
}

function regCommonEvent(select) {
  const titleDom = select.querySelector('.title')
  titleDom?.addEventListener('click', () => {
    if (select.classList.contains('disabled')) return

    const selectDomList = document.querySelectorAll('.select.expand')
    for (const sel of selectDomList) {
      if (sel !== select) {
        sel.classList.remove('expand')
      }
    }
    select.classList.toggle('expand')
  })

  const ulDom = select.querySelector('.options')
  ulDom?.addEventListener('click', (e) => {
    if (e.target.tagName.toLowerCase() !== 'li') return

    const beforeActiveLi = select.querySelector('li.active')
    beforeActiveLi && beforeActiveLi.classList.remove('active')
    e.target.classList.add('active')

    setTitleText(select, e.target.textContent)
    select.classList.remove('expand')
  })
}

function regProvinceEvent() {
  const ul = selProvinceRef.value?.querySelector('.options')
  ul.addEventListener('click', (e) => {
    if (e.target.tagName.toLowerCase() !== 'li') return
    const li = e.target
    const pr = selProvinceRef.value?.datas.find(
      (item) => item.label === li.textContent
    )
    fillSelect(selCityRef.value, pr.children)
    fillSelect(selAreaRef.value, [])
  })
}

function regCityEvent() {
  const ul = selCityRef.value?.querySelector('.options')
  ul.addEventListener('click', (e) => {
    if (e.target.tagName.toLowerCase() !== 'li') return
    const li = e.target
    const city = selCityRef.value?.datas.find(
      (item) => item.label === li.textContent
    )
    fillSelect(selAreaRef.value, city.children)
  })
}

function init() {
  fillSelect(selProvinceRef.value, datas.value)
  fillSelect(selCityRef.value, [])
  fillSelect(selAreaRef.value, [])

  regCommonEvent(selProvinceRef.value)
  regCommonEvent(selCityRef.value)
  regCommonEvent(selAreaRef.value)

  regProvinceEvent()
  regCityEvent()
}

onMounted(() => {
  init()
})
</script>

<style scoped lang="scss">
.cascader {
  box-sizing: border-box;
}

ul {
  padding: 0;
  margin: 0;
}

li {
  list-style: none;
}

.select {
  display: inline-block;
  margin: 0 5px;
  position: relative;
  white-space: nowrap;

  color: #666;
}

.title {
  min-width: 150px;
  height: 40px;
  line-height: 40px;
  padding: 0 10px;
  display: flex;
  justify-content: space-between;
  font-size: 14px;
  border: 1px solid #ccc;
  border-radius: 5px;
  cursor: pointer;
}

.title .iconfont {
  /* font-size: 10px; */
  transition: all 0.25s;
}

.options {
  font-size: 12px;
  border: 1px solid #ccc;
  border-radius: 5px;
  max-height: 300px;
  min-width: 100%;
  position: absolute;
  padding: 10px;
  top: 50px;
  background-color: #fff;

  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(auto-fit, 20px);
  /* 行间距 */
  row-gap: 6px;
  column-gap: 26px;
  /* 每一项左对齐 默认拉伸 */
  justify-items: left;
  box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);

  transform: scaleY(0);
  opacity: 0;
  transition: all 0.23s;
  transform-origin: 10px -10px;
}

.options li {
  cursor: pointer;
  padding: 3px 6px;
  border-radius: 5px;
}

.options li.active {
  background-color: #eec05a;
}

.options::before {
  content: '';
  width: 10px;
  height: 10px;
  position: absolute;
  left: 70px;
  top: -6px;
  border: 1px solid #ccc;
  transform: rotate(45deg);
  border-bottom: none;
  border-right: none;
  background-color: #fff;
}

.select.expand .options {
  transform: scaleY(1);
  opacity: 1;
}

.select.expand .iconfont {
  transform: rotate(180deg);
}

.select.disabled {
  color: #ccc;
}

.select.disabled .title {
  cursor: not-allowed;
}
</style>
